package com.yeskery.nut.extend.auth;

import com.yeskery.nut.core.*;

/**
 * 认证插件
 * @author sprout
 * 2022-06-02 10:26
 */
public class AuthPlugin extends AbstractAuthPlugin {

    /** 认证接口 */
    private Authenticate authenticate;

    /** 未授权处理器 */
    private RequestHandler unauthorizedHandler;

    /**
     * 构造认证插件
     * @param authenticate  认证接口
     * @param unauthorizedHandler 未授权处理器
     */
    public AuthPlugin(Authenticate authenticate, RequestHandler unauthorizedHandler) {
        this.authenticate = authenticate;
        this.unauthorizedHandler = unauthorizedHandler;
    }

    /**
     * 构造认证插件
     * @param authenticate  认证接口
     */
    public AuthPlugin(Authenticate authenticate) {
        this.authenticate = authenticate;
    }

    /**
     * 构造认证插件
     */
    public AuthPlugin() {
    }

    /**
     * 设置认证接口
     * @param authenticate  认证接口
     */
    public void setAuthenticate(Authenticate authenticate) {
        this.authenticate = authenticate;
    }

    /**
     * 设置未授权处理器
     * @param unauthorizedHandler  未授权处理器
     */
    public void setUnauthorizedHandler(RequestHandler unauthorizedHandler) {
        this.unauthorizedHandler = unauthorizedHandler;
    }

    @Override
    public boolean beforeHandle(Request request, Response response, Execution execution, Controller controller) throws Exception {
        if (authenticate == null) {
            throw new IllegalArgumentException("Authenticate Must Not Be Null.");
        }
        boolean notAuth = super.beforeHandle(request, response, execution, controller);
        if (notAuth) {
            return true;
        }

        boolean approve = authenticate.approve(request, controller);
        if (!approve) {
            if (unauthorizedHandler == null) {
                throw new ResponseNutException(ResponseCode.UNAUTHORIZED);
            } else {
                unauthorizedHandler.handle(request, response, execution);
                return false;
            }
        }
        return true;
    }

    @Override
    public int getOrder() {
        return Order.MAX;
    }
}
